<template>
  <div class="bpmn-editor-container h-screen flex flex flex-col">
    <!-- 顶部操作栏 -->
    <div class="toolbar bg-white border border-b p-3 flex justify-between items-center">
      <div class="flex gap-2">
        <a-button type="primary" @click="handleNew">
          <template #icon><plus-outlined /></template>
          新建
        </a-button>
        <a-button @click="handleImport">
          <template #icon><upload-outlined /></template>
          导入
        </a-button>
        <a-button @click="handleExport">
          <template #icon><download-outlined /></template>
          导出XML
        </a-button>
        <a-button @click="handleSave">
          <template #icon><save-outlined /></template>
          保存
        </a-button>
      </div>
      <div class="flex gap-2">
        <a-button @click="handleZoom('in')">
          <template #icon><zoom-in-outlined /></template>
          放大
        </a-button>
        <a-button @click="handleZoom('out')">
          <template #icon><zoom-out-outlined /></template>
          缩小
        </a-button>
        <a-button @click="handleZoom('fit')">
          <template #icon><retweet-outlined /></template>
          适应窗口
        </a-button>
      </div>
    </div>

    <!-- 主编辑区域 -->
    <div class="main-content flex flex-1 overflow-hidden">
      <!-- 左侧工具栏 -->
      <div class="left-toolbar w-16 bg-white border-r" ref="palette"></div>

      <!-- 中间画布区域 -->
      <div class="canvas-area flex-1 relative" ref="canvasContainer">
        <div ref="canvas" class="h-full w-full"></div>
        <input
          type="file"
          ref="fileInput"
          class="hidden"
          accept=".bpmn,.xml"
          @change="onFileChange"
        />
      </div>

      <!-- 右侧属性面板 -->
      <div class="right-panel w-80 bg-white border-l overflow-auto" ref="propertiesPanel"></div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, nextTick, onUnmounted } from 'vue';
import {
  PlusOutlined,
  UploadOutlined,
  DownloadOutlined,
  SaveOutlined,
  ZoomInOutlined,
  ZoomOutOutlined,
  RetweetOutlined
} from '@ant-design/icons-vue';
import { message } from 'ant-design-vue';

// 声明外部加载的模块类型
declare global {
  interface Window {
    BpmnModeler: any;
    bpmnJsPropertiesPanel: any;
    camundaBpmnModdle: any;
    bpmnZhCN: any;
    propertiesZhCN: any;
  }
}

// 组件引用
const canvas = ref<HTMLDivElement>(null);
const palette = ref<HTMLDivElement>(null);
const propertiesPanel = ref<HTMLDivElement>(null);
const canvasContainer = ref<HTMLDivElement>(null);
const fileInput = ref<HTMLInputElement>(null);

// BPMN模型器实例
let modeler: any = null;
// 当前XML内容
const currentXml = ref<string>('');

// 动态加载CDN资源
const loadCdnResources = async () => {
  // 创建加载脚本的函数
  const loadScript = (url: string): Promise<void> => {
    return new Promise((resolve, reject) => {
      const script = document.createElement('script');
      script.src = url;
      script.onload = () => resolve();
      script.onerror = () => reject(new Error(`Failed to load ${url}`));
      document.head.appendChild(script);
    });
  };

  // 创建加载样式的函数
  const loadStyle = (url: string): Promise<void> => {
    return new Promise((resolve, reject) => {
      const link = document.createElement('link');
      link.rel = 'stylesheet';
      link.href = url;
      link.onload = () => resolve();
      link.onerror = () => reject(new Error(`Failed to load ${url}`));
      document.head.appendChild(link);
    });
  };

  try {
    // 加载样式
    await Promise.all([
      loadStyle('https://unpkg.com/bpmn-js@18.6.3/dist/assets/diagram-js.css'),
      loadStyle('https://unpkg.com/bpmn-js@18.6.3/dist/assets/bpmn-font/css/bpmn.css'),
      loadStyle('https://unpkg.com/bpmn-js@18.6.3/dist/assets/bpmn-font/css/bpmn-codes.css'),
      loadStyle('https://unpkg.com/bpmn-js@18.6.3/dist/assets/bpmn-font/css/bpmn-embedded.css'),
      loadStyle('https://unpkg.com/@bpmn-io/properties-panel@3.33.0/dist/assets/properties-panel.css')
    ]);

    // 加载核心库
    await Promise.all([
      loadScript('https://unpkg.com/bpmn-js@18.6.3/dist/bpmn-modeler.development.js'),
      loadScript('https://unpkg.com/bpmn-js-properties-panel@5.42.0/dist/bpmn-js-properties-panel.development.js'),
      loadScript('https://unpkg.com/camunda-bpmn-moddle@7.0.1/dist/camunda-bpmn-moddle.development.js'),
      loadScript('https://unpkg.com/@bpmn-io/properties-panel@3.33.0/dist/index.umd.js')
    ]);

    // 加载中文语言包
    await Promise.all([
      loadScript('https://unpkg.com/bpmn-js@18.6.3/dist/locale/zh-CN.js'),
      loadScript('https://unpkg.com/bpmn-js-properties-panel@5.42.0/dist/locale/zh-CN.js')
    ]);

    console.log('所有CDN资源加载完成');
    return true;
  } catch (error) {
    console.error('CDN资源加载失败:', error);
    message.error('资源加载失败，请刷新页面重试');
    return false;
  }
};

// 初始化模型器
const initModeler = async () => {
  if (!canvas.value || !propertiesPanel.value || !palette.value) return;

  // 从全局对象获取加载的模块
  const { BpmnModeler } = window;
  const { 
    BpmnPropertiesPanelModule,
    BpmnPropertiesProviderModule,
    CamundaPlatformPropertiesProviderModule
  } = window.bpmnJsPropertiesPanel;
  const { CamundaBpmnModdle } = window.camundaBpmnModdle;
  
  // 中文语言包
  const bpmnZhCN = window.bpmnZhCN;
  const propertiesZhCN = window.propertiesZhCN;

  // 合并翻译
  const translations = {
    ...bpmnZhCN,
    propertiesPanel: {
      ...propertiesZhCN.propertiesPanel
    }
  };

  // 创建模型器实例
  modeler = new BpmnModeler({
    container: canvas.value,
    palette: {
      parent: palette.value
    },
    propertiesPanel: {
      parent: propertiesPanel.value
    },
    additionalModules: [
      BpmnPropertiesPanelModule,
      BpmnPropertiesProviderModule,
      CamundaPlatformPropertiesProviderModule
    ],
    moddleExtensions: {
      camunda: CamundaBpmnModdle
    },
    // 配置中文翻译
    translate: (key: string, options?: any) => {
      const keys = key.split('.');
      let value: any = translations;
      
      for (const k of keys) {
        if (value[k] === undefined) {
          return key;
        }
        value = value[k];
      }
      
      if (typeof value === 'function') {
        return value(options);
      }
      
      return value || key;
    }
  });

  // 监听事件
  const eventBus = modeler.get('eventBus');
  
  // 监听元素变化
  eventBus.on('element.changed', async () => {
    await updateXml();
  });

  // 创建新图
  await createNewDiagram();
};

// 创建新流程图
const createNewDiagram = async () => {
  if (!modeler) return;

  const defaultXml = `<?xml version="1.0" encoding="UTF-8"?>
    <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
      xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
      xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
      xmlns:camunda="http://camunda.org/schema/1.0/bpmn"
      id="Definitions_1"
      targetNamespace="http://camunda.org/examples">
      <process id="Process_1" isExecutable="true">
        <startEvent id="StartEvent_1" />
      </process>
      <bpmndi:BPMNDiagram id="BPMNDiagram_1">
        <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
          <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
            <dc:Bounds x="100" y="100" width="36" height="36" />
          </bpmndi:BPMNShape>
        </bpmndi:BPMNPlane>
      </bpmndi:BPMNDiagram>
    </definitions>`;

  try {
    const result = await modeler.importXML(defaultXml);
    if (result.warnings.length) {
      console.warn('导入警告:', result.warnings);
    }
    currentXml.value = defaultXml;
    // 适配视图
    modeler.get('canvas').zoom('fit-viewport');
    message.success('新流程图创建成功');
  } catch (err) {
    console.error('创建流程图失败:', err);
    message.error('创建流程图失败');
  }
};

// 更新XML内容
const updateXml = async () => {
  if (!modeler) return;

  try {
    const result = await modeler.saveXML({ format: true });
    currentXml.value = result.xml;
    return result.xml;
  } catch (err) {
    console.error('保存XML失败:', err);
    message.error('保存XML失败');
    return null;
  }
};

// 处理新建
const handleNew = () => {
  createNewDiagram();
};

// 处理导入
const handleImport = () => {
  if (fileInput.value) {
    fileInput.value.click();
  }
};

// 处理文件选择
const onFileChange = async (e: Event) => {
  if (!modeler) return;

  const target = e.target as HTMLInputElement;
  const file = target.files?.[0];
  
  if (!file) return;

  const reader = new FileReader();
  
  reader.onload = async (event) => {
    try {
      const xml = event.target?.result as string;
      const result = await modeler.importXML(xml);
      
      if (result.warnings.length) {
        console.warn('导入警告:', result.warnings);
        message.warning(`导入成功，但有${result.warnings.length}个警告`);
      } else {
        message.success('导入成功');
      }
      
      currentXml.value = xml;
      modeler.get('canvas').zoom('fit-viewport');
    } catch (err) {
      console.error('导入失败:', err);
      message.error('导入失败，请检查文件格式');
    }
  };
  
  reader.readAsText(file);
  target.value = ''; // 重置以允许重复选择同一文件
};

// 处理导出
const handleExport = async () => {
  if (!currentXml.value) {
    message.warning('没有可导出的内容');
    return;
  }

  try {
    const blob = new Blob([currentXml.value], { type: 'application/xml' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'diagram.bpmn';
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
    message.success('导出成功');
  } catch (err) {
    console.error('导出失败:', err);
    message.error('导出失败');
  }
};

// 处理保存
const handleSave = async () => {
  const xml = await updateXml();
  if (xml) {
    // 这里可以添加保存到服务器的逻辑
    console.log('保存的XML内容:', xml);
    message.success('保存成功');
  }
};

// 处理缩放
const handleZoom = (action: 'in' | 'out' | 'fit') => {
  if (!modeler) return;
  
  const canvas = modeler.get('canvas');
  
  switch (action) {
    case 'in':
      canvas.zoom('in');
      break;
    case 'out':
      canvas.zoom('out');
      break;
    case 'fit':
      canvas.zoom('fit-viewport');
      break;
  }
};

// 组件挂载时初始化
onMounted(async () => {
  await nextTick();
  // 先加载CDN资源，再初始化模型器
  const resourcesLoaded = await loadCdnResources();
  if (resourcesLoaded) {
    initModeler();
  }
});

// 组件卸载时清理
onUnmounted(() => {
  if (modeler) {
    modeler.destroy();
  }
});
</script>

<style scoped>
.bpmn-editor-container {
  display: flex;
  flex-direction: column;
  height: 100vh;
}

.main-content {
  flex: 1;
  display: flex;
  overflow: hidden;
}

.left-toolbar {
  width: 40px;
  background-color: #f5f5f5;
  border-right: 1px solid #e8e8e8;
}

.canvas-area {
  flex: 1;
  position: relative;
  overflow: hidden;
  background-color: #ffffff;
  background-image: 
    linear-gradient(rgba(128, 128, 128, 0.1) 1px, transparent 1px),
    linear-gradient(90deg, rgba(128, 128, 128, 0.1) 1px, transparent 1px);
  background-size: 20px 20px;
}

.right-panel {
  width: 300px;
  border-left: 1px solid #e8e8e8;
  overflow: auto;
}

.toolbar {
  background-color: #ffffff;
  border-bottom: 1px solid #e8e8e8;
  padding: 8px 16px;
}

/* 修复左侧工具栏图标显示 */
::v-deep .djs-palette {
  padding: 8px 0;
}

::v-deep .djs-palette .entry {
  width: 36px;
  height: 36px;
  margin: 0 auto 4px;
}

/* 修复属性面板样式 */
::v-deep .bpp-properties-panel {
  padding-bottom: 20px;
}

::v-deep .bpp-property-label {
  font-weight: 500;
}
</style>
